using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using Microsoft.Office.Server.Search.Administration;

namespace Carlsberg.SSPC.ContentSources.BO
{

    [XmlRoot("ContentSource")]
    public class ContentSourceInfo
    {

        private string name;
        private string tag;
        private List<string> startAddresses;
        private ScheduleInfo incrementalCrawlScheduleInfo;
        private ScheduleInfo fullCrawlScheduleInfo;
        private string contentSourceType;
        private int maxPageEnumerationDepth;
        private int maxSiteEnumerationDepth;
        private bool followDirectories;
        private int sharePointCrawlBehavior;


        [XmlAttribute]
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        [XmlAttribute]
        public string Tag
        {
            get { return tag; }
            set { tag = value; }
        }

        [XmlElement]
        public List<string> StartAddresses
        {
            get { return startAddresses; }
            set { startAddresses = value; }
        }

        [XmlElement]
        public ScheduleInfo IncrementalCrawlScheduleInfo
        {
            get { return incrementalCrawlScheduleInfo; }
            set { incrementalCrawlScheduleInfo = value; }
        }

        [XmlElement]
        public ScheduleInfo FullCrawlScheduleInfo
        {
            get { return fullCrawlScheduleInfo; }
            set { fullCrawlScheduleInfo = value; }
        }


        public ContentSourceInfo()
        {
        }

        [XmlAttribute]
        public string ContentSourceType
        {
            get { return contentSourceType; }
            set { contentSourceType = value; }
        }

        [XmlAttribute]
        public int MaxPageEnumerationDepth
        {
            get { return maxPageEnumerationDepth; }
            set { maxPageEnumerationDepth = value; }
        }

        [XmlAttribute]
        public int MaxSiteEnumerationDepth
        {
            get { return maxSiteEnumerationDepth; }
            set { maxSiteEnumerationDepth = value; }
        }

        [XmlAttribute]
        public bool FollowDirectories
        {
            get { return followDirectories; }
            set { followDirectories = value; }
        }

        [XmlAttribute]
        public int SharePointCrawlBehavior
        {
            get { return sharePointCrawlBehavior; }
            set { sharePointCrawlBehavior = value; }
        }

        public Type SharePointType
        {
            get
            {
                //Translate the type name to a strong type.
                //Could have used reflection to infer type, using simple switch
                //instead.
                //switch on content source type to save any special properties
                switch( contentSourceType )
                {
                    case "BusinessDataContentSource":
                        return typeof (BusinessDataContentSource);

                    case "CustomContentSource":
                        return typeof (CustomContentSource);

                    case "HierarchicalContentSource":
                        return typeof (HierarchicalContentSource);

                    case "SharePointContentSource":
                        return typeof (SharePointContentSource);

                    case "WebContentSource":
                        return typeof (WebContentSource);

                    case "ExchangePublicFolderContentSource":
                        return typeof (ExchangePublicFolderContentSource);

                    case "FileShareContentSource":
                        return typeof (FileShareContentSource);

                    default:
                    throw new ArgumentException("Unknown type of content source:" + contentSourceType, "contentSource");
                }
            }
        }

        public ContentSourceInfo(ContentSource contentSource)
        {
            name = contentSource.Name;


            startAddresses = new List<string>();
            foreach (Uri uri in contentSource.StartAddresses)
            {
                //TODO: Handle references to local server/farm
                startAddresses.Add(uri.AbsoluteUri);
            }
            tag = contentSource.Tag;

            if (contentSource.IncrementalCrawlSchedule != null)
            {
                incrementalCrawlScheduleInfo = new ScheduleInfo(contentSource.IncrementalCrawlSchedule);
            }
            if (contentSource.FullCrawlSchedule != null)
            {
                fullCrawlScheduleInfo = new ScheduleInfo(contentSource.FullCrawlSchedule);
            }

            //Handle various types of content sources
            contentSourceType = contentSource.GetType().Name;

            //switch on content source type to save any specialized properties
            if( contentSource is BusinessDataContentSource)
            {
                //no special properties
            }
            else if(contentSource is CustomContentSource)
            {
                followDirectories = ((CustomContentSource)contentSource).FollowDirectories;
                maxPageEnumerationDepth = ((CustomContentSource)contentSource).MaxPageEnumerationDepth;
                maxSiteEnumerationDepth= ((CustomContentSource)contentSource).MaxSiteEnumerationDepth;
            }
            else if(contentSource is HierarchicalContentSource)
            {
                followDirectories = ((HierarchicalContentSource) contentSource).FollowDirectories;                
            }
            else if(contentSource is SharePointContentSource)
            {
                sharePointCrawlBehavior = (int)((SharePointContentSource) contentSource).SharePointCrawlBehavior;
            }
            else if(contentSource is WebContentSource)
            {
                maxPageEnumerationDepth = ((WebContentSource) contentSource).MaxPageEnumerationDepth;
                maxSiteEnumerationDepth = ((WebContentSource) contentSource).MaxSiteEnumerationDepth;
            }
            else if( contentSource is ExchangePublicFolderContentSource)
            {
                //No special properties
            }
            else if( contentSource is FileShareContentSource)
            {
                //No special properties
            }
            else
            {
                throw new ArgumentException("Unknown type of content source:" + contentSourceType, "contentSource");
            }
        }

        /// <summary>
        /// Update/set the information in a SharePoint content source
        /// </summary>
        /// <param name="contentSource"></param>
        public void SetContentSourceProperties( ContentSource contentSource, SearchContext searchContext )
        {
            //Type sanity check
            if( contentSourceType != contentSource.GetType().Name )
            {
                throw new ArgumentException("Mismatched content source types, expected:"
                                            + contentSourceType
                                            + ", got:" + contentSource.GetType().Name, "contentSource");
            }

            //Name sanity check
            if( contentSource.Name != name)
            {
                throw new ArgumentException("Mismatched content source names, expected:"
                                            + name
                                            + ", got:" + contentSource.Name, "contentSource");                
            }

            //Set start addresses.
            contentSource.StartAddresses.Clear();
            foreach( string startAddr in startAddresses)
            {
                //TODO: Handle references to local server/farm
                contentSource.StartAddresses.Add(new Uri(startAddr));
            }

            //Read only
            //contentSource.Tag = tag;

            //Schedules
            if (incrementalCrawlScheduleInfo == null )
            {
                contentSource.IncrementalCrawlSchedule = null;
            }
            else{
                contentSource.IncrementalCrawlSchedule = incrementalCrawlScheduleInfo.GetSharePointSchedule(searchContext);
            }

            if (fullCrawlScheduleInfo == null)
            {
                contentSource.FullCrawlSchedule = null;
            }
            else
            {
                contentSource.FullCrawlSchedule = fullCrawlScheduleInfo.GetSharePointSchedule(searchContext);
            }

            //switch on content source type to update any special properties
            if (contentSource is BusinessDataContentSource)
            {
                //no special properties
            }
            else if (contentSource is CustomContentSource)
            {
                ((CustomContentSource) contentSource).FollowDirectories = followDirectories;
                ((CustomContentSource) contentSource).MaxPageEnumerationDepth = maxPageEnumerationDepth;
                ((CustomContentSource) contentSource).MaxSiteEnumerationDepth = maxSiteEnumerationDepth;
            }
            else if (contentSource is HierarchicalContentSource)
            {
                ((HierarchicalContentSource) contentSource).FollowDirectories = followDirectories;
            }
            else if (contentSource is SharePointContentSource)
            {
                ((SharePointContentSource)contentSource).SharePointCrawlBehavior = (SharePointCrawlBehavior) sharePointCrawlBehavior;
            }
            else if (contentSource is WebContentSource)
            {
                ((WebContentSource) contentSource).MaxPageEnumerationDepth = maxPageEnumerationDepth;
                ((WebContentSource) contentSource).MaxSiteEnumerationDepth = maxSiteEnumerationDepth;
            }
            else if (contentSource is ExchangePublicFolderContentSource)
            {
                //No special properties
            }
            else if (contentSource is FileShareContentSource)
            {
                //No special properties
            }
            else
            {
                throw new ArgumentException("Unknown type of content source:" + contentSourceType, "contentSource");
            }

        }
    }
}
